package com.m4f.city.utils.tag.datatable;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;

public class DataTableActionColumnTag extends BodyTagSupport implements IColumnTag {
	private String i18nName;
	private String name;
	private String jsFunctionName; // The name of the function that will be automatically generated.
	
	private String dataProp;
	
	//
	private String renderCallback;
	
	//
	private boolean bSortable;
	private boolean bSearchable;
	
	private List<ActionColumnTag> actions;
	private String urlBase;
	
	public DataTableActionColumnTag() {
		this.i18nName = "";
		this.name = "";
		this.dataProp = "";
		
		this.renderCallback = "";
		
		this.bSortable = false;
		this.bSearchable = false;
		this.urlBase = "";
		
	}
	
	public DataTableActionColumnTag(DataTableActionColumnTag col) {
		this();
		
		this.i18nName = col.getI18nName();
		this.name = col.getName();
		this.dataProp = col.getDataProp();
		
		this.renderCallback = col.getRenderCallback();
		
		this.bSortable = col.isbSortable();
		this.bSearchable = col.isbSearchable();
		
		this.jsFunctionName = col.getJsFunctionName();
		this.actions = col.getActions();
		this.urlBase = col.getUrlBase();
		 
	}
	
	@Override
	public int doStartTag() throws JspException {
		this.validateTag();
		this.actions = new ArrayList<ActionColumnTag>();
		this.urlBase = createURLBase();		
		
		return super.doStartTag();
	}
	
	@Override
	public int doEndTag() throws JspException {
		DataTableTag tag = (DataTableTag) getParent();
		tag.addCol(new DataTableActionColumnTag(this));
		return super.doEndTag();
	}
	
	// Interface methods
	@Override
	public boolean isActionsColumn() {
		return true;
	}
	
	@Override
	public String getColDefinition() {
		//("{ \"sName\": \"actions\", \"fnRender\" : make_crud_actions, \"bSortable\": false, \"bSearchable\": false },");
		StringBuffer sb = new StringBuffer();
		sb.append("{");
		// sName
		sb.append("\"sName\": \"");
		if(this.getName() != null && !("").equals(this.getName())) sb.append(this.getName());
		else sb.append(this.getDataProp());
		sb.append("\",");
		// fnRender
		if(isBlank(this.getRenderCallback()) && !(isBlank(this.getJsFunctionName()))) {
			if(this.getJsFunctionName() != null && !("").equals(this.getJsFunctionName())) sb.append("\"fnRender\": ").append(this.getJsFunctionName()).append(",");
		} else {
			if(this.getRenderCallback() != null && !("").equals(this.getRenderCallback())) sb.append("\"fnRender\": ").append(this.getRenderCallback()).append(",");
		}
		
		sb.append("},");
		
		return sb.toString();
	}
	
	@Override
	public String getJsFunctionDefinition() {
		StringBuffer sb = new StringBuffer();
		sb.append("function ").append(this.getJsFunctionName()).append("(oObj) {"); // TODO the name of the funtion!
		
		// var id = oObj.aData['id'];
		sb.append("var id = oObj.aData['id'];");
		if(actions != null) {
			for(ActionColumnTag action : this.actions) {
				//var detailAction = '<a href="<c:url value="/${rc.locale.language}/admin/application/detail/"/>' + id + '">Detail</a>';
				sb.append("var ").append(action.getName()).append(" = ").append("'<a href=\"");
				sb.append(getUrlBase()).append(action.getUrl()).append("' + id + '\">");
				sb.append(action.getI18nName());
				sb.append("</a>';");
			}
			sb.append("return ");
			for(int i = 0; i < actions.size() ; i++) {
				ActionColumnTag action = actions.get(i);
				sb.append(action.getName());
				if(i+1 < actions.size()) sb.append("+").append("'&nbsp;&nbsp;'").append("+");
			}
			
			sb.append(";");
		}
		
		sb.append("}");
		return sb.toString();
	}
	
	public void addAction(ActionColumnTag action) {
		this.actions.add(action);
	}
	
	private void validateTag() throws JspException {
		// TODO This validation is not valid, because an action column will never have a dataProp.
		if(!isBlank(this.getRenderCallback()) && !(isBlank(this.getJsFunctionName()))) throw new JspException("You only can set one of renderCallback or jsFunctionName properties, never both of them");
		else if(isBlank(this.getRenderCallback()) && (isBlank(this.getJsFunctionName()))) this.setJsFunctionName("m4ftag_" + this.getName()); 
	}

	private boolean isBlank(String property) {
		return property == null || ("").equals(property) ? true : false;
	}
	
	private String createURLBase() {
		StringBuffer sb = new StringBuffer();
		sb.append("http://").append(pageContext.getRequest().getServerName());
		if(pageContext.getRequest().getLocalPort() != 80) sb.append(":").append(pageContext.getRequest().getLocalPort());
		//if(!sb.toString().endsWith("/")) sb.append("/");
		return sb.toString();
	}
	
	// GETTERS AND SETTERS
	public String getI18nName() {
		return i18nName;
	}

	public void setI18nName(String i18nName) {
		this.i18nName = i18nName;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getDataProp() {
		return dataProp;
	}

	public void setDataProp(String dataProp) {
		this.dataProp = dataProp;
	}

	public String getRenderCallback() {
		return renderCallback;
	}

	public void setRenderCallback(String renderCallback) {
		this.renderCallback = renderCallback;
	}

	public boolean isbSortable() {
		return bSortable;
	}

	public void setbSortable(boolean bSortable) {
		this.bSortable = bSortable;
	}

	public boolean isbSearchable() {
		return bSearchable;
	}

	public void setbSearchable(boolean bSearchable) {
		this.bSearchable = bSearchable;
	}

	public String getJsFunctionName() {
		return jsFunctionName;
	}

	public void setJsFunctionName(String jsFunctionName) {
		this.jsFunctionName = jsFunctionName;
	}

	public List<ActionColumnTag> getActions() {
		return actions;
	}

	public String getUrlBase() {
		return urlBase;
	}

	public void setUrlBase(String urlBase) {
		this.urlBase = urlBase;
	}
}
